home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 2003 Cherry George Mathew <cherry@freeshell.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <linux/version.h>
- #include <linux/module.h>
- #include <linux/delay.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/interrupt.h>
- #include <linux/kdev_t.h>
- #include "pvcard.h"
- #include "pvcl.h"
- #include "pvproc.h"
- #include <asm/io.h>
- #include <asm/bitops.h>
-
- /* const declarations and static allocations */
-
- /* card ids ends with vendor id as marker. Number of cards is defined \
- * as MAX_CARDS. Will add PCI_DEVICE_ID_CIRRUS_5465 Later.
- */
- const int clgd54xx_card_id[]={PCI_DEVICE_ID_CIRRUS_5480,\
- PCI_DEVICE_ID_CIRRUS_5446,\
- PCI_VENDOR_ID_CIRRUS};
-
- /* Decided against kmalloc for the moment. Would probably be efficient
- * if we dealt with stuff like multiple cards, etc. not for the moment,
- * though.
- */
-
-
- /* Default max screen size hardcoded to ???? */
- static struct video_buffer vbuf_s = {
- };
-
- static struct video_picture vpict_s;
-
- /* TODO: Chroma keying.....Default _no_ chromakeying bcos xawtv has no
- * support for it with V4L1. Someday.... Sigh ......*/
-
- static struct video_window vwin_s = {
- /* chromakey: GD_CHROMA_KEY, */
- /* flags: VIDEO_WINDOW_CHROMAKEY */
- };
-
- /* Tuner properties hardcoded. */
- static struct video_tuner vtun_s = {
- name: "Television",
- rangelow: 0,
- rangehigh: 0x7FFFFFFF,
- flags: VIDEO_TUNER_PAL,
- mode: VIDEO_MODE_PAL
- };
-
- /* Single channel support at the moment. S-Video and Composite ignored. */
- static struct video_channel vchan_s = {
- name: "Television",
- tuners: 1,
- flags: VIDEO_VC_TUNER | VIDEO_VC_AUDIO,
- type: VIDEO_TYPE_TV,
- norm: VIDEO_MODE_PAL
- };
-
- static struct gd_status_t dstat_s = {
- vbuf_p: &vbuf_s,
- vwin_p: &vwin_s,
- vtun_p: &vtun_s,
- vchan_p: &vchan_s,
- vpict_p: &vpict_s,
- };
-
- /* Initializing a new adapter named clgd54xx. Right now, we'll make do
- with a static declaration. Not good enough for driving multiple cards.
- */
-
-
- static struct clgd54xx_card clgd54xx_card_info = {
- spun_lock: SPIN_LOCK_UNLOCKED,
- drv_stat_p: &dstat_s,
- model: PVCLPP_COMBO
- };
-
- static struct i2c_algo_bit_data clgd54xx_bitbang_adap = {
- data: &clgd54xx_card_info,
- setsda: gd54xx_setsda,
- setscl: gd54xx_setscl,
- getsda: gd54xx_getsda,
- getscl: gd54xx_getscl,
- udelay: 16,
- mdelay: 10,
- timeout: 200,
- };
-
- static struct i2c_adapter clgd54xx_adap = {
- name: "clgd54xx",
-
- /* Now make i2c_adapter->algo_data point to our
- * i2c_algo_bit_data , ie; link adapter and algo.
- */
-
- id: I2C_ALGO_BIT | I2C_HW_B_BT848,
- algo_data: &clgd54xx_bitbang_adap,
- };
-
- /* variable declarations and initializations */
-
- unsigned int debug = 0;
- unsigned int re_entry = 0;
-
- /* Adapter - Low level functions */
-
- /* Note:
- * 5480 and 5446B can use either MMIO or PIO
- * 5446A must use PIO
- * 5465 must use MMIO
- */
-
- unsigned io_readb(unsigned port)
- {
- vprintk("io_io_read on port %p\n", (char *) port);
- return inb(port);
- }
-
- void io_writeb(unsigned data, unsigned port)
- {
- vprintk("io_io_write on port %p\n", (char *) port);
- outb(data, port);
- }
-
- /*************** TODO: IMPLEMENT PCI MEM MAPPING *****************
-
-
- unsigned m_io_readb_proc(unsigned port)
- {
- vprintk("m_io_read on port %p\n", (char *) port);
- return readb(port);
- }
-
- void m_io_writeb_proc(unsigned data, unsigned port)
- {
- vprintk("m_io_write on port %p\n", (char *) port);
- writeb(data, port);
- }
-
- *************************************************************************/
- void gd_write_sr(struct clgd54xx_card *card_p,unsigned char datum,unsigned reg)
- {
- spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
- io_writeb(reg, card_p->gd_io_base + GD_SR_OFFSET);
- io_writeb(datum, card_p->gd_io_base + GD_SR_OFFSET + 1);
- spin_unlock_irqrestore(&card_p->spun_lock, card_p->spinflags);
-
- }
-
-
- void gd_write_gr(struct clgd54xx_card *card_p, unsigned char datum,unsigned reg)
- {
- spin_lock_irqsave(&card_p->spun_lock,card_p->spinflags);
- io_writeb(reg, card_p->gd_io_base + GD_GR_OFFSET);
- io_writeb(datum, card_p->gd_io_base + GD_GR_OFFSET + 1);
- spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
-
- }
-
- void gd_write_cr(struct clgd54xx_card *card_p, unsigned char datum,unsigned reg)
- {
- spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
- io_writeb(reg, card_p->gd_io_base + GD_CR_OFFSET);
- io_writeb(datum, card_p->gd_io_base + GD_CR_OFFSET + 1);
- spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
-
- }
-
- unsigned gd_read_sr(struct clgd54xx_card *card_p, unsigned reg)
- {
- unsigned value;
- spin_lock_irqsave(&card_p->spun_lock,card_p->spinflags);
- io_writeb(reg, card_p->gd_io_base + GD_SR_OFFSET);
- value = io_readb(card_p->gd_io_base + GD_SR_OFFSET + 1);
- spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
- return value;
- }
-
- unsigned gd_read_gr(struct clgd54xx_card *card_p, unsigned reg)
- {
- unsigned value;
- spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
- io_writeb(reg, card_p->gd_io_base + GD_GR_OFFSET);
- value = io_readb(card_p->gd_io_base + GD_GR_OFFSET + 1);
- spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
- return value;
- }
-
- unsigned gd_read_cr(struct clgd54xx_card *card_p, unsigned reg)
- {
- unsigned value;
- spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
- io_writeb(reg, card_p->gd_io_base + GD_CR_OFFSET);
- value = io_readb(card_p->gd_io_base + GD_CR_OFFSET + 1);
- spin_unlock_irqrestore(&card_p->spun_lock, card_p->spinflags);
- return value;
- }
-
-
- void gd54xx_setsda (void *bit_adap_dat, int state)
- {
- struct clgd54xx_card *data=bit_adap_dat;
-
- /* Switch on I2C interface */
- set_bit(6, &data->i2c_state);
-
- /* Set/Clear bit */
- state ? set_bit(1, &(data->i2c_state)) : clear_bit(1, &(data->i2c_state));
-
- gd_write_sr(data, data->i2c_state, 0x8);
- }
-
- void gd54xx_setscl (void *bit_adap_dat, int state)
- {
- struct clgd54xx_card *data=bit_adap_dat;
-
- set_bit(6, &data->i2c_state);
- state ? set_bit(0, &(data->i2c_state)) : clear_bit(0, &(data->i2c_state));
-
- gd_write_sr(data, data->i2c_state, 0x8);
- }
-
- int gd54xx_getsda (void *bit_adap_dat)
- {
- struct clgd54xx_card *data=bit_adap_dat;
-
- return (((data->i2c_state = gd_read_sr(data, 0x8)) >>7)&0x1);
-
- return 0;
- }
-
- int gd54xx_getscl (void *bit_adap_dat)
- {
- struct clgd54xx_card *data=bit_adap_dat;
- return (((data->i2c_state = gd_read_sr(data, 0x8)) >>2)&0x1);
- return 0;
- }
-
- /* Adapter functions - high level */
-
- int i2c_clgd54xx_init_adapter(struct clgd54xx_card *card_p,
- struct i2c_adapter * adap,
- struct i2c_algo_bit_data * bitadap)
- {
-
- /* Let's initialize some of the data structures.
- * First plug in card adapter and card bit bang algo
- * into card info.
- */
-
- card_p->clgd54xx_adapter_p = adap;
- card_p->clgd54xx_bitbang_adapter_p = bitadap;
-
- return i2c_bit_add_bus(card_p->clgd54xx_adapter_p);
-
- }
-
- int i2c_clgd54xx_cleanup_adapter(struct clgd54xx_card *card_p){
-
- return i2c_bit_del_bus(card_p->clgd54xx_adapter_p);
- }
-
- int i2c_clgd54xx_probe_card(struct clgd54xx_card *card_p)
- {
- card_p->gd_io_base=0;
-
- /* Memory Mapped IO not supported at the moment.
- * This driver won't work for multiple cards.
- */
- return 0;
- }
-
- int i2c_clgd54xx_find_card(struct clgd54xx_card *card_p){
-
- struct pci_dev *dev = NULL;
- int loop_count=0;
- do{
- if ((dev = pci_find_device(clgd54xx_card_id[MAX_CARDS],clgd54xx_card_id[loop_count], dev))) {
-
- printk(KERN_INFO
- "pvcl: Found %s\n", dev->name);
- card_p->clgd54xx_pci_dev_p = dev;
- card_p->clgd54xx_pci_dev_id =
- clgd54xx_card_id[loop_count];
-
- printk(KERN_INFO
- "pvcl: Detected %dMB video ram.\n",
- gd_count_ram(card_p));
-
- return 0;
- }
- loop_count++;
- } while(clgd54xx_card_id[loop_count]!=clgd54xx_card_id[MAX_CARDS]);
-
- printk(KERN_WARNING
- "pvcl: Sorry. Could not find a Cirrus Logic Chip.\n");
- return -ENODEV;
-
- }
-
-
- /*
- * gd_count_ram() is hacked from gd5480.c from the xtv package.
- * xtv is copyrighted to Itai Nahshon <nahshon@actcom.co.il>.
- * Used with permission from the author.
- */
-
-
- int
- gd_count_ram(struct clgd54xx_card *card_p)
- {
- int videoram = 1;
- int SR0F, SR17;
-
- unsigned short chip_type = card_p->clgd54xx_pci_dev_id;
-
- switch (chip_type) {
- case PCI_DEVICE_ID_CIRRUS_5446:
- videoram = 1;
-
- SR0F = gd_read_sr(card_p, 0x0F);
- SR17 = gd_read_sr(card_p, 0x17);
- if ((SR0F & 0x18) == 0x18) {
- if(SR0F & 0x80) {
- if(SR17 & 0x80)
- videoram = 2;
- else if(SR17 & 0x02)
- videoram = 3;
- else
- videoram = 4;
- }
- else {
- if((SR17 & 80) == 0)
- videoram = 2;
- }
- }
- break;
-
- case PCI_DEVICE_ID_CIRRUS_5480:
- videoram = 1;
- SR0F = gd_read_sr(card_p, 0x0F);
- if ((SR0F & 0x18) == 0x18) { /* 2 or 4 MB */
- videoram = 2;
- if (SR0F & 0x80) /* Second bank enable */
- videoram = 4;
- }
- break;
-
- case PCI_DEVICE_ID_CIRRUS_5465:
- videoram = 4;
- break;
- }
-
- card_p->vram = videoram;
- return videoram;
- }
-
-
- int __init i2c_clgd54xx_init(struct clgd54xx_card *card_p,
- struct i2c_adapter *adap,
- struct i2c_algo_bit_data *bitadap)
- {
- int ret_val;
-
- /* This adapter is non-re-entrant at the moment */
-
- if(re_entry) return -EBUSY;
-
- re_entry = 1;
-
- if( (ret_val = i2c_clgd54xx_find_card(card_p)) ){
- return ret_val;
- }
-
- if( (ret_val = i2c_clgd54xx_probe_card(card_p)) ){
- return ret_val;
- }
-
- if( (ret_val = i2c_clgd54xx_init_adapter(card_p, adap, bitadap)) ){
- return ret_val;
- }
-
- return ret_val;
- }
-
- int __init i2c_clgd54xx_cleanup(struct clgd54xx_card *card_p)
- {
- re_entry=0;
-
- return i2c_clgd54xx_cleanup_adapter( card_p );
-
- }
-
- /* i2c client support */
- void do_client_ioctl(struct file *file, unsigned int cmd, void *arg)
- {
- struct clgd54xx_card *card_p = file->private_data;
- struct i2c_adapter *adap = card_p->clgd54xx_adapter_p;
-
- int i;
-
- for (i = 0; i < I2C_CLIENT_MAX; i++) {
- if (NULL == adap->clients[i])
- continue;
- if (NULL == adap->clients[i]->driver->command)
- continue;
- adap->clients[i]->driver->command(
- adap->clients[i],cmd,arg);
- }
-
-
- }
-
- /* VGA support functions. */
-
- /* gd_bit_copy() - used for copying data to/from VGA registers */
-
- void gd_bit_copy(unsigned long * dest, int dest_start,
- unsigned long * src, int src_start, int src_stop)
- {
- for(; src_start<= src_stop; src_start++, dest_start++)
- {
- if(test_bit(src_start, src))
- set_bit(dest_start, dest);
- else
- clear_bit(dest_start, dest);
- }
-
- }
-
- void gd_enable_window(struct clgd54xx_card * card_p)
- {
- unsigned long CR3E, CR50, CR51, CR58, CR5C;
-
- CR3E = gd_read_cr(card_p, 0x3e);
- CR50 = gd_read_cr(card_p, 0x50);
- CR51 = gd_read_cr(card_p, 0x51);
- CR58 = gd_read_cr(card_p, 0x58);
- CR5C = gd_read_cr(card_p, 0x5c);
-
- /* Disable Teletext CR5C[7] = 0 */
- clear_bit(7, &CR5C);
-
- /* Capture all frames CR50[7], CR50[2], CR58[6] = 0,0,0 */
-
- clear_bit(7, &CR50);
- clear_bit(2, &CR50);
- clear_bit(6, &CR58);
-
- /* Set Capture input to VPORT CR50[1:0] = 11 */
-
- set_bit(0, &CR50); /* Falling edge of HREF ends */
- set_bit(1, &CR50); /* capture line. */
-
- /* Enable Capture CR51[3] = 1 */
- set_bit(3, &CR51);
-
- /* Enable Video Window CR3E[0] = 1 */
- set_bit(0, &CR3E);
-
- gd_write_cr(card_p, CR5C, 0x5c);
- gd_write_cr(card_p, CR58, 0x58);
- gd_write_cr(card_p, CR51, 0x51);
- gd_write_cr(card_p, CR50, 0x50);
- gd_write_cr(card_p, CR3E, 0x3e);
-
- }
-
- void gd_disable_window(struct clgd54xx_card * card_p)
- {
- unsigned long CR3E, CR50, CR51;
-
- CR3E = gd_read_cr(card_p, 0x3e);
- CR50 = gd_read_cr(card_p, 0x50);
- CR51 = gd_read_cr(card_p, 0x51);
-
-
- /* Disable Capture CR51[3] = 0 */
- clear_bit(3, &CR51);
-
- /* Reset Capture input to standard feature
- connector CR50[1:0] = 11 */
-
- clear_bit(0, &CR50); /* Falling edge of HREF ends capture */
- clear_bit(1, &CR50);
-
- /* Disable Video Window CR3E[0] = 0 */
- clear_bit(0, &CR3E);
-
-
- gd_write_cr(card_p, CR51, 0x51);
- gd_write_cr(card_p, CR50, 0x50);
- gd_write_cr(card_p, CR3E, 0x3e);
- }
-
- void gd_set_vbuf1(struct clgd54xx_card * card_p, unsigned long ptr)
- {
- unsigned long CR3A, CR3B, CR3C, CR5D;
-
-
- CR3A = gd_read_cr(card_p, 0x3a);
- CR3B = gd_read_cr(card_p, 0x3b);
- CR3C = gd_read_cr(card_p, 0x3c);
- CR5D = gd_read_cr(card_p, 0x5d);
-
- /* CR5D[3:2] = ptr[1:0] */
-
- gd_bit_copy( &CR5D, 2, &ptr, 0, 1);
-
- /* CR3A = ptr[9:2] */
-
- gd_bit_copy( &CR3A, 0, &ptr, 2, 9);
-
-
- /* CR3B = ptr[17:10] */
-
- gd_bit_copy(&CR3B, 0, &ptr, 10, 17);
-
- /* CR3C[3:0] = ptr[21:18] */
-
- gd_bit_copy(&CR3C, 0, &ptr, 18, 21);
-
- gd_write_cr(card_p, CR3A, 0x3a);
- gd_write_cr(card_p, CR3B, 0x3b);
- gd_write_cr(card_p, CR3C, 0x3c);
- gd_write_cr(card_p, CR5D, 0x5d);
-
- }
-
- void gd_set_vbuf2(struct clgd54xx_card * card_p, unsigned long ptr)
- {
- unsigned long CR59, CR5A, CR58, CR5D;
-
- CR59 = gd_read_cr(card_p, 0x59);
- CR5A = gd_read_cr(card_p, 0x5a);
- CR58 = gd_read_cr(card_p, 0x58);
- CR5D = gd_read_cr(card_p, 0x5d);
-
- /* CR5D[3:2] = ptr[1:0] */
-
- gd_bit_copy(&CR5D, 2, &ptr, 0, 1);
-
- /* CR59 = ptr[9:2] */
-
- gd_bit_copy(&CR59, 0, &ptr, 2, 9);
-
- /* CR5A = ptr[17:10] */
-
- gd_bit_copy(&CR5A, 0, &ptr, 10, 17);
-
- /* CR58[3:0] = ptr[21:18] */
-
- gd_bit_copy(&CR58, 0, &ptr, 18, 21);
-
- gd_write_cr(card_p, CR59, 0x59);
- gd_write_cr(card_p, CR5A, 0x5a);
- gd_write_cr(card_p, CR58, 0x58);
- gd_write_cr(card_p, CR5D, 0x5d);
-
- }
-
- unsigned long gd_get_vbuf1(struct clgd54xx_card * card_p)
- {
- unsigned long CR3A, CR3B, CR3C, CR5D;
- unsigned long ptr;
-
- CR3A = gd_read_cr(card_p, 0x3a);
- CR3B = gd_read_cr(card_p, 0x3b);
- CR3C = gd_read_cr(card_p, 0x3c);
- CR5D = gd_read_cr(card_p, 0x5d);
-
- /* ptr[1:0] = CR5D[3:2] */
- ptr = 0;
- gd_bit_copy( &ptr, 0, &CR5D, 2, 3);
-
- /* ptr[9:2] = CR3A */
-
- gd_bit_copy( &ptr, 2, &CR3A, 0, 7);
-
-
- /* ptr[17:10] = CR3B */
-
- gd_bit_copy(&ptr, 10, &CR3B, 0, 7);
-
- /* ptr[21:18] = CR3C[3:0] */
-
- gd_bit_copy(&ptr, 18, &CR3C, 0, 3);
-
- return ptr;
-
- }
-
-
- unsigned long gd_get_vbuf2(struct clgd54xx_card * card_p)
- {
- unsigned long CR59, CR5A, CR58, CR5D;
- unsigned long ptr;
-
- CR59 = gd_read_cr(card_p, 0x59);
- CR5A = gd_read_cr(card_p, 0x5a);
- CR58 = gd_read_cr(card_p, 0x58);
- CR5D = gd_read_cr(card_p, 0x5d);
-
- /* ptr[1:0] = CR5D[3:2] */
- ptr = 0;
- gd_bit_copy(&ptr, 0, &CR5D, 2, 3);
-
- /* ptr[9:2] = CR59 */
-
- gd_bit_copy(&ptr, 2, &CR59, 0, 7);
-
- /* ptr[17:10] = CR5A */
-
- gd_bit_copy(&ptr, 10, &CR5A, 0, 7);
-
- /* ptr[21:18] = CR58[3:0] */
-
- gd_bit_copy(&ptr, 18, &CR58, 0, 3);
- return ptr;
-
- }
-
- void gd_set_pitch(struct clgd54xx_card * card_p, unsigned long offset)
- {
- unsigned long CR3C, CR3D;
-
- CR3C = gd_read_cr(card_p, 0x3c);
- CR3D = gd_read_cr(card_p, 0x3d);
-
- /* CR3C[5] = offset[11], CR3D = offset[10:3] */
-
- gd_bit_copy(&CR3C, 5, &offset ,11, 11);
-
- gd_bit_copy(&CR3D, 0, &offset, 3, 10);
-
- gd_write_cr(card_p, CR3C, 0x3c);
- gd_write_cr(card_p, CR3D, 0x3d);
-
- }
-
-
- unsigned long gd_get_pitch(struct clgd54xx_card * card_p)
- {
-
- unsigned long CR3C, CR3D;
- unsigned long offset ;
-
-
- CR3C = gd_read_cr(card_p, 0x3c);
- CR3D = gd_read_cr(card_p, 0x3d);
-
- /* offset[11] = CR3C[5] , offset[10:3] = CR3D */
- offset = 0;
- gd_bit_copy(&offset, 11, &CR3C, 5, 5);
- gd_bit_copy(&offset, 3, &CR3D, 0, 7);
-
- return offset;
- }
-
-
-
- void gd_init_video( struct clgd54xx_card * card_p )
- {
- unsigned long temp_reg;
- unsigned long CR31, CR32, CR3E, CR3F, CR50, CR51, CR56,
- CR57, CR58, CR5C, CR5E;
-
- /* unsigned long GRC, GRD; */
-
- CR31 = gd_read_cr(card_p, 0x31);
- CR32 = gd_read_cr(card_p, 0x32);
- CR3E = gd_read_cr(card_p, 0x3e);
- CR3F = gd_read_cr(card_p, 0x3f);
- CR50 = gd_read_cr(card_p, 0x50);
- CR51 = gd_read_cr(card_p, 0x51);
- CR56 = gd_read_cr(card_p, 0x56);
- CR57 = gd_read_cr(card_p, 0x57);
- CR58 = gd_read_cr(card_p, 0x58); /* Dependancy only on maxheight */
- CR5C = gd_read_cr(card_p, 0x5c);
- CR5E = gd_read_cr(card_p, 0x5e);
-
-
- /* GRC = gd_read_gr(card_p, 0x0c); */
- /* GRD = gd_read_gr(card_p, 0x0d); */
-
- /* Set the maximum scanlines to 512, we don't want
- * wanton clipping. */
-
- temp_reg = 0xff;
- gd_bit_copy(&CR57, 0, &temp_reg, 0, 7);
- set_bit(5, &CR58);
-
- /* Luminance only capture disabled */
- /* CR5C[5] = 0 */
-
- clear_bit(5, &CR5C);
-
- /* Count lines upto capture, set to zero */
- /* CR56[4:0] = 0 */
-
- temp_reg = 0;
- gd_bit_copy(&CR56, 0, &temp_reg, 0, 4);
-
- /* Non - Interlaced capture */
- /* CR50[6] = 0 */
-
- clear_bit(6, &CR50);
-
- /* 8bits, VPort width */
- /* CR50[4] = 0; */
-
- clear_bit(4, &CR50);
-
- /* Double clock capture */
- /* CR50[3] = 1; */
-
- set_bit(3, &CR50);
-
-
- /* Video Capture (Not Teletext) */
- /* CR5C[7] = 0 */
-
- clear_bit(7, &CR5C);
-
- /* Capture Data Format - YUV 4:2:2 */
- /* CR51[2:0] = 000 */
-
- clear_bit(0, &CR51);
- clear_bit(1, &CR51);
- clear_bit(2, &CR51);
-
- /* Display Data Format - YUV 4:2:2 */
- /* CR3E[3:1] = 000 */
- /* CR3F[4] = 0 */
-
- clear_bit(1, &CR3E);
- clear_bit(2, &CR3E);
- clear_bit(3, &CR3E);
- clear_bit(4, &CR3F);
-
- /* Double Buffer Control - Autoswitch */
- /* CR5E[5:4] = 10 */
-
- clear_bit(4, &CR5E);
- set_bit(5, &CR5E);
-
-
- /* Set Zoom = 1:1 ie., ZoomX = ZoomY = 0 */
- /* ZoomX = CR31, ZoomY = CR32 */
- CR31 = CR32 = 0;
-
- /* Also, Zoom mode set to 1; ie; line replication,
- * in anticipation of chromakeying..
- */
- set_bit(4, &CR3E);
-
- /* Occlusion set to Colour Key, tagged compare (16 bit). */
- /* CR1D[5:3] = 011 */
-
- /* set_bit(3, &CR1D); */
- /* clear_bit(4, &CR1D); */
- /* clear_bit(5, &CR1D); */
-
-
-
- /* Set the Chroma key. */
-
- /* GRC = 0; */
- /* GRD = GD_CHROMA_KEY; */
-
- /* Switch on Chromakeying */
- /* set_bit(7, &CR3E); */
-
- /* gd_write_gr(card_p, GRC, 0x0c); */
- /* gd_write_gr(card_p, GRD, 0x0d); */
-
- gd_write_cr(card_p, CR50, 0x50);
- gd_write_cr(card_p, CR51, 0x51);
- gd_write_cr(card_p, CR56, 0x56);
- gd_write_cr(card_p, CR57, 0x57);
- gd_write_cr(card_p, CR58, 0x58); /* May be safely removed with Mx ht.*/
- gd_write_cr(card_p, CR5C, 0x5c);
- gd_write_cr(card_p, CR5E, 0x5e);
- gd_write_cr(card_p, CR31, 0x31);
- gd_write_cr(card_p, CR32, 0x32);
- gd_write_cr(card_p, CR3E, 0x3e);
- gd_write_cr(card_p, CR3F, 0x3f);
- }
-
- void gd_get_window(struct clgd54xx_card * card_p,
- struct video_window *winstruct,
- struct video_buffer * vbuf)
- {
- int depth;
- unsigned long R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO;
- unsigned long CR33, CR34, CR35, CR36, CR37, CR38, CR39, CR5D;
-
- depth = (vbuf->depth == 32 ? 24 : vbuf->depth);
- CR33 = gd_read_cr(card_p, 0x33);
- CR34 = gd_read_cr(card_p, 0x34);
- CR35 = gd_read_cr(card_p, 0x35);
- CR36 = gd_read_cr(card_p, 0x36);
- CR37 = gd_read_cr(card_p, 0x37);
- CR38 = gd_read_cr(card_p, 0x38);
- CR39 = gd_read_cr(card_p, 0x39);
- CR5D = gd_read_cr(card_p, 0x5d);
-
-
- /* R1SZ = CR36[1:0] CR33 */
- R1SZ = 0;
- gd_bit_copy(&R1SZ, 8, &CR36, 0, 1);
- gd_bit_copy(&R1SZ, 0, &CR33, 0, 7);
-
- /* R1Adjust = CR5D[1:0] */
-
- R1Adjust = 0;
- gd_bit_copy(&R1Adjust, 0, &CR5D, 0, 1);
-
- /* R2SZ = CR36[3:2] CR34 */
- R2SZ = 0;
- gd_bit_copy(&R2SZ, 8, &CR36, 2, 3);
- gd_bit_copy(&R2SZ, 0, &CR34, 0, 7);
-
- /* R2Adjust = CR5D[5:4] */
- R2Adjust = 0;
- gd_bit_copy(&R2Adjust, 0, &CR5D, 4, 5);
-
- /* R2DSZ = CR36[5:4] CR35 */
- R2DSZ = 0;
- gd_bit_copy(&R2DSZ, 8, &CR36, 4, 5);
- gd_bit_copy(&R2DSZ, 0, &CR35, 0, 7);
-
- /* WVS = CR39[1:0] CR37 */
- WVS = 0;
- gd_bit_copy(&WVS, 8, &CR39, 0, 1);
- gd_bit_copy(&WVS, 0, &CR37, 0, 7);
-
- /* WVE = CR39[3:2] CR38 */
- WVE = 0;
- gd_bit_copy(&WVE, 8, &CR39, 2, 3);
- gd_bit_copy(&WVE, 0, &CR38, 0, 7);
-
- WAO = 0;
-
- WAO = gd_get_pitch(card_p);
-
-
- tprintk("gd_get_window() hardware registers read:\n
- depth = %d bpp \n
- R1SZ = %ld\n
- R1Adjust = %ld\n
- R2SZ = %ld\n
- R2Adjust = %ld\n
- R2DSZ = %ld\n
- WVS=%ld\n WVE=%ld\n
- WAO=%ld\n", depth,
- R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO);
-
- winstruct->x = R1SZ * 32 / depth + R1Adjust * 8 / depth;
-
- winstruct->width = R2SZ * 32 / depth + R2Adjust * 8 / depth;
-
- winstruct->y = WVS;
- winstruct->height = WVE - WVS;
-
- }
-
-
- void gd_set_window(struct clgd54xx_card * card_p,
- struct video_window *winasked,
- struct video_window *wingiven,
- struct video_buffer *vbuf)
- {
- int depth;
- unsigned long R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO;
- unsigned ZOOMY, CR32;
- unsigned long CR33, CR34, CR35, CR36, CR37, CR38, CR39, CR5D;
-
- depth = (vbuf->depth == 32 ? 24 : vbuf->depth);
-
- /* Safety Checks and clipping, for window borders. */
-
- winasked->x = winasked->x < 0 ?
- 0 : winasked->x;
-
- winasked->y = winasked->y < 0 ?
- 0 : winasked->y;
-
- winasked->width = (vbuf->width - winasked->x) < winasked->width ?
- (vbuf->width - winasked->x) : winasked->width;
-
- winasked->height = (vbuf->height - winasked->y) < winasked->height ?
- (vbuf->height - winasked->y) : winasked->height;
-
-
- R1SZ = (winasked->x * depth) / 32;
- R1Adjust = (winasked->x * depth - R1SZ * 32) / 8;
-
- R2SZ = (winasked->width * depth) / 32;
- R2Adjust = (winasked->width * depth - R2SZ * 32) / 8;
-
- /*ugly hack. only tried on 24bpp and 16bpp eqn is. vbpp/gbpp * .5 */
-
- R2DSZ = R2SZ * 16 / depth + R2Adjust * 4 / depth;
-
- WVS = winasked->y;
-
- WVE = WVS + winasked->height;
-
- WAO = R2SZ * 4;
-
- /* Zoom treatment. Doing zoom just for Vlines.
- * Notes: Occlusion, ie; chromakeying and line interpolation
- * (in the case of zooming) are mutually exclusive.
- */
-
- if(wingiven->height < winasked->height)
- {
- ZOOMY = (wingiven->height * 256) / winasked->height - 5;
- CR32 = ZOOMY;
- }
- else
- CR32 = 0; /* Don't want old Zoom values lying about. */
-
-
-
- /* CR36[1:0] CR33 = R1SZ */
- gd_bit_copy(&CR36, 0, &R1SZ, 8, 9);
- gd_bit_copy(&CR33, 0, &R1SZ, 0, 7);
-
- /* CR5D[1:0] = R1Adjust */
- gd_bit_copy(&CR5D, 0, &R1Adjust, 0, 1);
-
- /* CR36[3:2] CR34 = R2SZ */
- gd_bit_copy(&CR36, 2, &R2SZ, 8, 9);
- gd_bit_copy(&CR34, 0, &R2SZ, 0, 7);
-
- /* CR5D[5:4] = R2Adjust */
-
- gd_bit_copy(&CR5D, 4, &R2Adjust, 0, 1);
-
- /* CR36[5:4] CR35 = R2DSZ */
-
- gd_bit_copy(&CR36, 4, &R2DSZ, 8, 9);
- gd_bit_copy(&CR35, 0, &R2DSZ, 0, 7);
-
- /* CR39[1:0] CR37 = WVS */
-
- gd_bit_copy(&CR39, 0, &WVS, 8, 9);
- gd_bit_copy(&CR37, 0, &WVS, 0, 7);
-
- /* CR39[3:2] CR38 = WVE */
-
- gd_bit_copy(&CR39, 2, &WVE, 8, 9);
- gd_bit_copy(&CR38, 0, &WVE, 0, 7);
-
- /* CR36[5:4] CR35 = R2DSZ */
-
- gd_bit_copy(&CR36, 4, &R2DSZ, 8, 9);
- gd_bit_copy(&CR35, 0, &R2DSZ, 0, 7);
-
- gd_set_pitch(card_p, WAO);
-
- tprintk("gd_set_window() hardware registers set to:\n
- R1SZ = %ld\n
- R1Adjust = %ld\n
- R2SZ = %ld\n
- R2Adjust = %ld\n
- R2DSZ = %ld\n
- WVS=%ld\n WVE=%ld\n
- WAO=%ld\n",
- R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO);
-
- gd_write_cr(card_p, CR5D, 0x5d);
- gd_write_cr(card_p, CR39, 0x39);
- gd_write_cr(card_p, CR38, 0x38);
- gd_write_cr(card_p, CR37, 0x37);
- gd_write_cr(card_p, CR36, 0x36);
- gd_write_cr(card_p, CR35, 0x35);
- gd_write_cr(card_p, CR34, 0x34);
- gd_write_cr(card_p, CR33, 0x33);
- gd_write_cr(card_p, CR32, 0x32);
- }
-
- /* returns clipped windows, according to available ram, with
- * video buffer starting as close to the end of video ram as possible.
- */
-
- long gd_window_init(struct clgd54xx_card * card_p)
- {
-
- int scrn_depth;
- unsigned long vbuf1_ptr, vbuf2_ptr, scrn_ht, scrn_wt, vram;
-
- vram = card_p->vram = gd_count_ram(card_p);
-
- scrn_ht = card_p->drv_stat_p->vbuf_p->height;
- scrn_wt = card_p->drv_stat_p->vbuf_p->width;
- scrn_depth = card_p->drv_stat_p->vbuf_p->depth;
- scrn_depth = scrn_depth == 32 ? 24 :scrn_depth;
-
- vbuf1_ptr = vram * 1048576 - 16384 - scrn_ht * scrn_wt * 2;
-
- /* Eeeks!!! No check for video data spilling over into framebuffer
- * space. OK folk. Get ready for full screen video!
-
- if(vbuf1_ptr < (scrn_ht * scrn_wt * scrn_depth / 8)) return -1;
-
- */
-
- vbuf2_ptr = vbuf1_ptr;
-
- gd_init_video(card_p);
-
- printk("Marker \n");
-
- gd_set_vbuf1(card_p, vbuf1_ptr);
- gd_set_vbuf2(card_p, vbuf2_ptr);
-
- return vbuf2_ptr;
-
- }
-
- /* V4L Driver Callback functions */
-
- static int pvcl_open(struct inode *inode, struct file *file)
- {
-
- unsigned int minor = minor(inode->i_rdev);
- struct clgd54xx_card * card_p;
-
-
- file->private_data = &clgd54xx_card_info;
- card_p = file->private_data;
-
- do_client_ioctl(file, VPROC_INIT, &card_p->model);
-
- dprintk("pvcl_open called on minor %d\n", minor);
-
- return 0;
- }
-
- static int pvcl_release(struct inode *inode, struct file *file)
- {
- file->private_data = NULL;
-
- dprintk("pvcl_release called.\n");
- return 0;
- }
-
- static int pvcl_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
- {
-
- struct clgd54xx_card * card_p = file->private_data;
-
- switch(cmd) {
-
- case VIDIOCGCAP:
- {
- struct video_capability *cap = arg;
- struct video_buffer *bufstat =
- card_p->drv_stat_p->vbuf_p;
-
- sprintf(cap->name, "pvcl");
-
- cap->type = VID_TYPE_TUNER | VID_TYPE_OVERLAY |
- VID_TYPE_FRAMERAM | VID_TYPE_SCALES;
-
- cap->channels = 1; /* Just one channel for now. */
- cap->audios = 1;
-
- /* Max Screen Size reported by X11 via v4l-conf */
- cap->maxwidth = bufstat->width;
- cap->maxheight = bufstat->height;
- cap->minwidth = 32; /* Hardcoded vpx 3225D specific */
- cap->minheight = 24;
-
- /* Hard Code PAL for the moment. */
-
- do_client_ioctl(file, VPROC_SET_CAP_MODE,
- &card_p->drv_stat_p->vtun_p->mode);
-
- dprintk("VIDIOCGCAP called\n");
-
- return 0;
- }
-
- case VIDIOCGFBUF:
- {
- struct video_buffer *buf = arg;
- struct video_buffer *bufstat =
- card_p->drv_stat_p->vbuf_p;
-
- memcpy(buf, bufstat, sizeof(*buf));
-
- dprintk("VIDIOCGFBUF called. \n");
-
- return 0;
-
- }
-
- case VIDIOCSFBUF:
- {
-
- struct video_buffer *buf = arg;
- struct video_buffer *bufstat =
- card_p->drv_stat_p->vbuf_p;
-
-
- /* HEEEEEEEEEEEEELOOOOOOOOOOOOOOOO, Careful. Security
- hole here!!!!!!!!!!!
- */
- /* Security check disabled for now.
- if(!capable(CAP_SYS_ADMIN) &&
- !capable(CAP_SYS_RAWIO))
- return -EPERM;
- */
-
- memcpy(bufstat, buf, sizeof(*bufstat));
-
- dprintk("VIDIOCSFBUF called. \n");
- printk(KERN_INFO "client reports:\n
- screen size: %dx%d @ %dbpp.
- %d bytesperline.\n.",
- bufstat->width,
- bufstat->height,
- bufstat->depth,
- bufstat->bytesperline);
-
- dprintk("Capture Buffer set to 0x%p", bufstat->base);
-
- /* Now that we've got the Screen Parms,
- * we can inititialize the window */
-
- gd_window_init(card_p);
-
- return 0;
- }
-
-
- case VIDIOCCAPTURE:
- {
- int *on = arg;
- struct video_buffer *bufstat =
- card_p->drv_stat_p->vbuf_p;
-
- if (*on) {
- /* verify args */
- if (NULL == bufstat->base)
- return -EINVAL;
- if (bufstat->width <32 ||
- bufstat->height <24 ||
- bufstat->width >800 ||
- bufstat->height >600)
-
- return -EINVAL;
- }
-
- if(*on) {
-
-
- /* Tell vpx to switch on. `on' is dummy here.*/
-
- do_client_ioctl(file, VPROC_START_CAPTURE, on);
- gd_enable_window(card_p);
-
- dprintk("VIDIOCCAPTURE: video window switched on. \n");
- return 0;
- }
-
- else {
-
- /* Tell vpx to stop capture. `on' is dummy.*/
-
- do_client_ioctl(file, VPROC_STOP_CAPTURE, on);
-
- gd_disable_window(card_p);
-
- dprintk("VIDIOCCAPTURE: video window switched off. \n");
- return 0;
- }
-
- }
-
- case VIDIOCGWIN:
- {
- struct video_window *winarg = arg;
- struct video_window *winstat =
- card_p->drv_stat_p->vwin_p;
-
- memcpy(winarg, winstat, sizeof(*winarg));
-
- /* TODO: Need to get actual window parms from
- * hardware. Use gd_get_video_window()
- */
-
- dprintk("VIDIOCGWIN called. \n");
- return 0;
- }
-
-
- case VIDIOCSWIN:
- {
- struct video_window *winarg = arg;
- struct video_window *winstat =
- card_p->drv_stat_p->vwin_p;
- struct video_buffer *bufstat =
- card_p->drv_stat_p->vbuf_p;
-
- memcpy(winstat, winarg, sizeof(*winstat));
-
-
- tprintk("VIDIOCSWIN recieved:\n
- \t position: %d, %d \n
- \t dimensions: %d, %d \n",
- winstat->x,
- winstat->y,
- winstat->width,
- winstat->height);
-
- do_client_ioctl(file, VPROC_SET_WINDOW, winarg);
-
- /* gd_set_window(card_p, app_wants, vproc_gives....) */
-
- gd_set_window(card_p, winstat, winarg, bufstat);
-
- tprintk("gd_set_window() recieved:\n
- \t position: %d, %d \n
- \t dimensions: %d, %d \n",
- winstat->x,
- winstat->y,
- winstat->width,
- winstat->height);
-
- gd_get_window(card_p, winstat, bufstat);
-
- tprintk("gd_get_window returned: \n
- \t position: %d, %d \n
- \t dimensions: %d, %d \n",
- winstat->x,
- winstat->y,
- winstat->width,
- winstat->height);
-
-
- dprintk("VIDIOCSWIN called. \n");
- return 0;
- }
-
- /* Wrappers for tuner.c - hacked from bttv-driver.c
- which is copyrighted to :
-
- Copyright (C) 1996,97,98
- Ralph Metzler <rjkm@thp.uni-koeln.de>,
- Marcus Metzler <mocm@thp.uni-koeln.de>,
- &
- (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
-
- */
-
- case VIDIOCGTUNER:
- {
- struct video_tuner *v = arg;
- struct video_tuner *vstat =
- card_p->drv_stat_p->vtun_p;
-
- if (v->tuner) /* Only tuner 0 */
- return -EINVAL;
-
- do_client_ioctl(file,cmd,v);
-
- /* tuner.c returns v->signal, ie; signal strength. */
- memcpy(v, vstat, sizeof(*v));
-
- dprintk("VIDIOCGTUNER has been called. \n");
- return 0;
-
- }
-
- case VIDIOCSTUNER:
- {
- struct video_tuner *v = arg;
- struct video_tuner *vstat =
- card_p->drv_stat_p->vtun_p;
-
- if (v->tuner) /* Only tuner 0 */
- return -EINVAL;
- if (v->mode > VIDEO_MODE_PAL)
- return -EINVAL;
-
- do_client_ioctl(file,cmd,v);
-
- vstat->mode = v->mode;
-
- dprintk("VIDIOCSTUNER has been called. \n");
-
- return 0;
- }
-
- case VIDIOCGFREQ:
- {
- unsigned long *freq = arg;
- *freq = card_p->drv_stat_p->freq;
- dprintk("VIDIOCGFREQ called.\n");
-
- return 0;
- }
- case VIDIOCSFREQ:
- {
- unsigned long *freq = arg;
-
- do_client_ioctl(file,cmd,freq);
-
- card_p->drv_stat_p->freq=*freq;
- dprintk("VIDIOCSFREQ called.\n");
-
- return 0;
- }
-
- case VIDIOCSCHAN:
- {
- struct video_channel *v = arg;
- struct video_tuner *vstat = card_p->drv_stat_p->vtun_p;
-
- if (v->channel > 0)
- return -EINVAL;
-
- if(v->norm > VIDEO_MODE_PAL)
- return -EINVAL;
-
- /* TODO: need to implement tv norms.
- * Currently hardcoded
- * to PAL. See struct video_channel
- * vchan_s decl above. */
-
- do_client_ioctl(file,cmd,v);
-
- memcpy(vstat, v , sizeof(*v));
- dprintk("VIDIOCSCHAN has been called. \n");
- return 0;
- }
-
- case VIDIOCGCHAN:
- {
- struct video_channel *v = arg;
- struct video_channel *chanstat =
- card_p->drv_stat_p->vchan_p;
-
- memcpy(v, chanstat, sizeof(*v));
-
- dprintk("VIDIOCGCHAN has been called. \n");
-
- return 0;
- }
-
- /* End bttv-driver.c wrappers. */
-
-
- case VIDIOCGPICT:
- {
- struct video_picture *vpict = arg;
- struct video_picture *vpictstat =
- card_p->drv_stat_p->vpict_p;
-
- memcpy(vpict, vpictstat, sizeof(*vpict));
-
- dprintk("VIDIOCGPICT has been called. \n");
- }
-
-
- case VIDIOCSPICT:
- {
- struct video_picture *vpict = arg;
- struct video_picture *vpictstat =
- card_p->drv_stat_p->vpict_p;
-
- memcpy(vpictstat, vpict, sizeof(*vpict));
-
- do_client_ioctl(file, VPROC_SET_PICTURE, vpictstat);
-
- dprintk("VIDIOCGPICT has been called. \n");
- }
- }
-
- return -ENOIOCTLCMD;
-
-
-
- }
-
-
- static int pvcl_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
- {
- return video_usercopy(inode, file, cmd, arg, pvcl_do_ioctl);
- }
-
- static ssize_t pvcl_read(struct file *file, char *data,
- size_t count, loff_t *ppos)
- {
- return 0;
- }
-
- static struct file_operations pvcl_fops =
- {
- owner: THIS_MODULE,
- open: pvcl_open,
- release: pvcl_release,
- ioctl: pvcl_ioctl,
- llseek: no_llseek,
- read: pvcl_read
- };
-
- static struct video_device pvcl_video_dev =
- {
- name: "PVCL ver 0.1",
- type: VID_TYPE_TUNER | VID_TYPE_OVERLAY |
- VID_TYPE_FRAMERAM | VID_TYPE_SCALES,
- fops: &pvcl_fops,
- minor: -1
- };
-
-
- /* Device Registration */
- static int __devinit pvcl_register_video(struct video_device * video_dev )
- {
- if(video_register_device(video_dev, VFL_TYPE_GRABBER, 0)<0)
- return -1;
- printk(KERN_INFO "pvcl: registered device video\n");
-
- return 0;
-
-
- }
-
- static void __devexit pvcl_unregister_video(struct video_device * video_dev)
- {
- video_unregister_device(video_dev);
- }
-
- static int pvcl_init_module(void)
- {
- int retval;
-
- if( (retval = pvcl_register_video( &pvcl_video_dev)) ) return retval;
- if( (retval = i2c_clgd54xx_init(&clgd54xx_card_info,
- &clgd54xx_adap,
- &clgd54xx_bitbang_adap)) )
- return retval;
-
- switch(debug)
- {
- case 1:
- {
- printk(KERN_INFO "pvcl: Functional Debug messages enabled.\n");
- break;
- }
- case 2:
- {
- printk(KERN_INFO "pvcl: Debug messages enabled per function.\n");
- break;
- }
- case 3:
- printk(KERN_INFO "pvcl: WARNING: Verbose Debugging enabled - kernel printk buffers may overflow.\n");
- break;
- }
-
-
- return retval;
-
- }
-
- static void pvcl_cleanup_module(void)
- {
- i2c_clgd54xx_cleanup(&clgd54xx_card_info);
- pvcl_unregister_video(&pvcl_video_dev);
- }
-
- module_init(pvcl_init_module);
- module_exit(pvcl_cleanup_module);
-
- MODULE_PARM(debug,"i");
- MODULE_PARM_DESC(debug,"debug messages, default 0, is don't debug.");
-
- MODULE_DESCRIPTION("pvcl - v4l driver module for the pixelview combo tv plus");
- MODULE_AUTHOR("Cherry George Mathew");
- MODULE_LICENSE("GPL");
-
- /*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-